<template>
    <a-popup
        ref="popup"
        popPlacement="right-start"
        :popModifiers="popModifiers"
        v-model:popShown="popShown"
        :escToClose="false"
    >
        <textarea
            class="a-input-textarea"
            :disabled="myDisabled"
            :readonly="readonly"
            :class="[
                `color-${myColor}`,
                `size-${mySize}`,
                { sharp: mySharp },
                { disabled: myDisabled },
                formItem ? 'c-f-grow-1' : '',
            ]"
            :value="value"
            :placeholder="placeholder"
            :rows="rows"
            @input="input($event.target.value)"
        ></textarea>
        <template v-slot:pop>
            <a-button
                :color="myColor"
                :size="mySize"
                :sharp="mySharp"
                :square="true"
                :link="true"
                @click="clear"
            >
                <span class="fa fa-fw fa-remove"></span>
            </a-button>
        </template>
    </a-popup>
</template>

<style lang="scss" scoped>
@use "sass:math";
@import "../scss/vars";

.a-input-textarea {
    width: 280px;
    box-sizing: border-box;
    outline: none;
    transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
    font-family: inherit;
    resize: vertical;

    @each $colorPackageName, $colorPackageValue in $colorPackages {
        $bgColor: map-get($colorPackageValue, "bgColor");

        &.color-#{$colorPackageName} {
            color: map-get($colorPackageValue, "themeColor");
            background-color: $defaultBgColor;
            border: solid 1px $bgColor;

            &:focus:not(.disabled) {
                border-color: darken($bgColor, 20%);
                box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
                    0 0 8px lighten($bgColor, 10%);
            }

            &.disabled {
                opacity: 0.5;
                cursor: not-allowed;
            }
        }
    }

    @each $sizePackageName, $sizePackageValue in $sizePackages {
        &.size-#{$sizePackageName} {
            padding: math.div(map-get($sizePackageValue, "space"), 2)
                map-get($sizePackageValue, "space");
            font-size: map-get($sizePackageValue, "fontSize");
            &:not(.sharp) {
                border-radius: map-get($sizePackageValue, "borderRadius");
            }
        }
    }
}
</style>

<script>
import APopup from './APopup.vue'
import AButton from './AButton.vue'
import utils from "../common/utils"
import inputMixin from "../common/inputMixin"
import AScrollable from './AScrollable.vue'

export default {
    components: { APopup, AButton, AScrollable },
    mixins: [inputMixin],
    emits: ['clear'],
    props: {
        readonly: {
            type: Boolean,
            default: false,
        },
        value: {
            type: String,
            default: null
        },
        clearable: {
            type: Boolean,
            default: true,
        },
        placeholder: {
            type: String,
            default: null
        },
        rows: {
            type: Number,
            default: 5
        }
    },
    data() {
        return {
            popShown: false,
            prepareToHide: false,
        }
    },
    computed: {
        sizePackage() {
            return utils.getSizePackageByName(this.mySize)
        },
        popModifiers() {
            return [
                {
                    name: 'offset',
                    options: {
                        offset: [0, -this.sizePackage.size],
                    }
                },
                {
                    name: 'preventOverflow',
                    options: {
                        mainAxis: false,
                        altAxis: false,
                    }
                }
            ]
        },
        diff() {
            let maxLengthRule = this.rules.find(a => a.name == 'maxLength')
            if (!maxLengthRule) {
                return null
            }
            let valueLength = this.value?.length ?? 0
            return {
                valid: valueLength <= maxLengthRule.value,
                text: `${valueLength}/${maxLengthRule.value}`
            }
        },
        /**
         * 由于value已经在mixin中被watch，这里要继续watch value的话，就会覆盖mixin的watch了，所以换一个值名称
         */
        valueCloneForWatch(){
            return this.value
        },
    },
    mounted() {
        this.addTargetEventListener()
        this.setDiffResult()
    },
    watch: {
        valueCloneForWatch(val) {
            if (!val) {
                this.popShown = false
            } else if (this.getTargetEl() == window.document.activeElement) {
                this.popShown = true
            }
        },
        popShown(val) {
            if (val) {
                this.addPopEventListener()
            }
        },
        diff() {
            this.setDiffResult()
        }
    },
    methods: {
        input(val) {
            this.$emit('update:value', val)
        },
        getTargetEl() {
            return this.$refs.popup.getTargetEl()
        },
        getPopEl() {
            return this.$refs.popup.getPopEl()
        },
        addTargetEventListener() {
            let targetEl = this.getTargetEl()
            targetEl.addEventListener('mouseover', this.onMouseover)
            targetEl.addEventListener('mouseout', this.onMouseout)
        },
        addPopEventListener() {
            this.$nextTick(() => {
                let popEl = this.getPopEl()
                popEl.addEventListener('mouseover', this.onMouseover)
                popEl.addEventListener('mouseout', this.onMouseout)
            })
        },
        onMouseover(e) {
            if (!this.clearable || !this.value) {
                return
            }
            this.popShown = true
            this.prepareToHide = false
        },
        onMouseout(e) {
            this.prepareToHide = true
            setTimeout(() => {
                if (this.prepareToHide) {
                    this.popShown = false
                }
            }, 50)
        },
        clear() {
            if (!this.readonly) {
                this.input(null)
                this.getTargetEl()?.focus()
            }
            this.$emit('clear')
        },
        setDiffResult() {
            let diff = this.diff
            this.formItem?.setDiffResult(diff?.valid, diff?.text)
        },
    }
}
</script>